
package com.shkg.opencloud.fastdfs.controller;


import com.shkg.opencloud.common.bo.ApiResult;
import com.shkg.opencloud.common.bo.ApiResultUtil;
import com.shkg.opencloud.fastdfs.entity.UploadFile;
import com.shkg.opencloud.fastdfs.enums.MultipartfileStatusEnum;
import com.shkg.opencloud.fastdfs.service.AccessFileService;
import com.shkg.opencloud.fastdfs.util.MultipartFileUtil;
import com.shkg.opencloud.idsc.servers.fileaccess.dto.UploadFileDTO;
import com.shkg.opencloud.idsc.servers.fileaccess.feign.FastdfsServerInterface;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 文件批量的上传、下载
 */
@RestController
@RequestMapping("/dfs")
@Api(value = "文件服务上传下载接口", description = "文件服务上传下载接口")
public class AccessFileController {

    private Logger logger = LoggerFactory.getLogger(AccessFileController.class);


    @Autowired
    private AccessFileService accessFileService;


    /**
     * 单个文件上传 结果返回
     *
     * @param file
     * @param cid
     * @return Map<>
     * @throws IOException
     */
    @PostMapping(value = "/uploadFile")
    @ApiOperation(value = "单个文件上传")
    @ResponseBody
    public ApiResult<UploadFileDTO> uploadFile(@RequestParam("file") MultipartFile file, @RequestParam("cid") String cid) {
        if (file == null || file.getSize() == 0) {
            return ApiResultUtil.failure(MultipartfileStatusEnum.F300);
        }
        UploadFileDTO dto = accessFileService.uploadFile(file, cid);
        return ApiResultUtil.ok(dto);
    }


    /**
     * 批量上传文件到fastdfs服务器
     *
     * @param files
     * @param cid   用户ID
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/uploadFiles")
    @ApiOperation(value = "批量上传文件(多文件，请用postman测试，swagger会异常)")
    public ApiResult<Map<String, UploadFileDTO>> uploadFiles(@RequestParam("files") MultipartFile[] files, @RequestParam("cid") String cid) {
        if (files == null || files.length == 0) {
            return ApiResultUtil.failure(MultipartfileStatusEnum.F300);
        }
        for (MultipartFile file : files) {
            logger.debug("====> 接收文件{}", file.getOriginalFilename());
        }
        return ApiResultUtil.ok(accessFileService.batUploadFile(files, cid));
    }


    /**
     * 单个图片上传到fastdfs服务器
     *
     * @param file
     * @param cid
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/uploadImage")
    @ApiOperation(value = "单个上传图片")
    @ResponseBody
    public ApiResult<UploadFileDTO> uploadImage(@RequestParam("file") MultipartFile file, @RequestParam("cid") String cid) {
        if (file == null || file.getSize() == 0) {
            return ApiResultUtil.failure(MultipartfileStatusEnum.F300);
        }
        UploadFileDTO dto = accessFileService.uploadImage(file, cid);
        return ApiResultUtil.ok(dto);
    }


    /**
     * 单个图片上传到fastdfs服务器
     * <p>
     * "会员照片(base64 编码格式)，大小不 超过 1M，尺寸最 大 1280*1280",name="base64",example = "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")
     *
     * @param base64Image
     * @param cid
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/uploadBase64Image")
    @ApiOperation(value = "单个上传图片", notes = "照片(base64 编码格式)，大小不 超过 1M，尺寸最 大 1280*1280 ,在传输数据的时候，需去掉 ‘data:image/png;base64,’; fileName需要携带正确的文件类型后缀")
    @ResponseBody
    public ApiResult<UploadFileDTO> uploadBase64Image(@RequestParam("base64Image") String base64Image, @RequestParam("fileName") String fileName, @RequestParam("cid") String cid) {
        if (base64Image == null || base64Image.length() == 0) {
            return ApiResultUtil.failure(MultipartfileStatusEnum.F300);
        }

        byte[] imgByte = Base64.decodeBase64(base64Image);
        InputStream in = new ByteArrayInputStream(imgByte);

        MultipartFile file = null;
        try {
            file = new MultipartFileUtil("file", fileName, in);
        } catch (IOException e) {
            return ApiResultUtil.failure(MultipartfileStatusEnum.F200);
        }

        UploadFileDTO dto = accessFileService.uploadImage(file, cid);
        return ApiResultUtil.ok(dto);
    }


    /**
     * 批量上传图片到fastdfs服务器
     *
     * @param files
     * @param cid
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/uploadImages", produces = {MediaType.APPLICATION_JSON_UTF8_VALUE}, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    @ApiOperation(value = "批量上传图片(多文件，请用postman测试，swagger会异常)")
    @ResponseBody
    public ApiResult<Map<String, UploadFileDTO>> uploadImages(@RequestParam("files") MultipartFile[] files, @RequestParam("cid") String cid) {
        if (files == null || files.length == 0) {
            return ApiResultUtil.failure(MultipartfileStatusEnum.F300);
        }
        for (MultipartFile file : files) {
            logger.debug("====> 接收文件{}", file.getOriginalFilename());
        }
        return ApiResultUtil.ok(accessFileService.batUploadImage(files, cid));
    }


    /**
     * 批量上传图片到fastdfs服务器
     *
     * @param files
     * @param cids  用户ID
     * @return
     * @throws IOException
     */
    @PostMapping(value = "/uploadImageOne2One")
    @ApiOperation(value = "批量上传文件(多文件，请用postman测试，swagger会异常)")
    public ApiResult<Map<String, UploadFileDTO>> uploadImageOne2One(@RequestParam("files") MultipartFile[] files, @RequestParam("cids") String cids) {
        if (files == null || files.length == 0) {
            return ApiResultUtil.failure(MultipartfileStatusEnum.F300);
        }
        for (MultipartFile file : files) {
            logger.debug("====> 接收文件{}", file.getOriginalFilename());
        }


        return ApiResultUtil.ok(accessFileService.uploadImageOne2One(files, cids));
    }


    /**
     * 单个文件/图片下载
     *
     * @param filesMD5
     * @param response
     */
    @PostMapping(value = "/downloadFileByFilesMD5")
    @ApiOperation(value = "根据filesMD5单个文件/图片下载")
    public void downloadFileByFilesMD5(@RequestParam String filesMD5, @RequestParam String cid, HttpServletResponse response) throws IOException {

        UploadFile fileInfo = accessFileService.getFileByMd5(cid, filesMD5);
        if (fileInfo != null) {
            downloadFile(fileInfo.getFilesPath(), fileInfo.getFilesName(), response);
        }
    }


    /**
     * 根据外键FK  下载图片   返回访问连接地址的集合
     */
    @PostMapping(value = "/downloadFilesByForeignKey")
    @ApiOperation(value = "根据外键foreignKey 查询文件/图片列表")
    public ApiResult<List<UploadFileDTO>> downloadFilesByForeignKey(@RequestParam String foreignKey) {
        return ApiResultUtil.ok(accessFileService.getFileByFk(foreignKey));
    }


    /**
     * 根据外键FK  下载图片   返回访问连接地址的集合
     */
    @PostMapping(value = "/downloadLastFileByForeignKey")
    @ApiOperation(value = "根据外键foreignKey最后一个文件/图片下载")
    public ApiResult<String> downloadLastFileByForeignKey(@RequestParam String foreignKey) {
        return ApiResultUtil.ok(accessFileService.getLastFileByFk(foreignKey));
    }


    /**
     * 根据外键FK  下载图片   返回访问连接地址的集合
     */
    @PostMapping(value = "/downloadLastFileByForeignKeys")
    @ApiOperation(value = "根据外键foreignKey的list 查询每个业务外键的最后一个图片地址，并返回键值对（form传值）")
    public ApiResult<Map<String, String>> downloadLastFileByForeignKeys(@RequestParam List<String> foreignKeys) {
        return ApiResultUtil.ok(accessFileService.getLastFilesByFks(foreignKeys));
    }


    /**
     * 根据外键FK  下载图片   返回访问连接地址的集合
     */
    @PostMapping(value = "/downloadLastFileByFKS")
    @ApiOperation(value = "根据外键foreignKey的list 查询每个业务外键的最后一个图片地址，并返回键值对(body传值)")
    public ApiResult<Map<String, String>> downloadLastFileByFKS(@ApiParam(value = "业务外键id集合", required = true) @RequestBody List<String> fks) {
        return ApiResultUtil.ok(accessFileService.getLastFilesByFks(fks));
    }


    /**
     * 根据文件的MD5和cid删除文件
     * true删除成功   false删除失败
     * <p>
     * 如果 md5 + fk 确定有多条信息，则仅删除 数据库中的记录
     * <p>
     * 如果 md5 + fk 确定仅有一条信息，则删处数据库记录 + fdfs文件
     */
    @PostMapping(value = "/deleteByFilesMD5")
    @ApiOperation(value = "根据文件的MD5和cid删除文件")
    @Transactional
    public ApiResult<Boolean> deleteByFilesMD5(@RequestParam String filesMD5, @RequestParam String cid) {
        return accessFileService.delFileByMd5(cid, filesMD5);
    }


    /**
     * 根据 业务外键删除所有关联的文件
     * true删除成功   false删除失败
     * <p>
     * 如果 fk 确定有多条信息，则仅删除 数据库中的记录
     * <p>
     * 如果 fk 确定仅有一条信息，则删处数据库记录 + fdfs文件
     */
    @PostMapping(value = "/deleteByFK")
    @ApiOperation(value = "根据文件的MD5和cid删除文件")
    @Transactional
    public ApiResult<Boolean> deleteByFK(@RequestParam String cid) {
        return accessFileService.delFileByFK(cid);
    }


    ////////////////////////////////////////////////////////////////
    // 以下为内部接口
    /////////////////// /////////////////////////////////////////////


    /**
     * private
     * 下载文件(图片)公共方法
     *
     * @param filesName
     * @param filesPath group1/M00/00/00/wKg7g1wN2YyAAH1MAADJbaKmScw004.jpg
     */
    private void downloadFile(String filesPath, String filesName, HttpServletResponse response) throws IOException {
        //这里的filesPath需要是这种格式的：group1/M00/00/00/wKg7g1wN2YyAAH1MAADJbaKmScw004.jpg
        byte[] bytes = accessFileService.download(filesPath);
        //支持中文名称，避免乱码
        response.setContentType("application/force-download");
        response.addHeader("Content-Disposition", "attachment;fileName=" + new String(filesName.getBytes("UTF-8"), "iso-8859-1"));
        response.setCharacterEncoding("UTF-8");
        OutputStream outputStream = response.getOutputStream();
        outputStream.write(bytes);
    }

}

